package com.example.selfservicestation.activity

import android.app.Activity
import android.os.Bundle
import android.util.DisplayMetrics
import android.util.Log
import android.view.View
import android.view.WindowManager
import androidx.core.os.bundleOf
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.example.selfservicestation.R
import com.example.selfservicestation.adapter.TextlineAdapter
import com.example.selfservicestation.base.BaseBindingActivity
import com.example.selfservicestation.constant.DEFAULT_CARD_DOOR_PORT
import com.example.selfservicestation.constant.DEFAULT_CARD_PORT
import com.example.selfservicestation.constant.DEFAULT_DOOR_OPEN_TIME
import com.example.selfservicestation.constant.DEFAULT_LOCK_CARD
import com.example.selfservicestation.constant.DEFAULT_LOCK_COUNT
import com.example.selfservicestation.constant.DEFAULT_LOCK_PORT
import com.example.selfservicestation.constant.DEFAULT_LOGIN_CARD
import com.example.selfservicestation.constant.EXTRA_LOCK_ON_NUM
import com.example.selfservicestation.constant.SP_CARD_DOOR_PORT
import com.example.selfservicestation.constant.SP_CARD_PORT
import com.example.selfservicestation.constant.SP_DOOR_OPEN_TIME
import com.example.selfservicestation.constant.SP_LOCK_CARD
import com.example.selfservicestation.constant.SP_LOCK_COUNT
import com.example.selfservicestation.constant.SP_LOCK_PORT
import com.example.selfservicestation.constant.SP_LOGIN_CARD
import com.example.selfservicestation.constant.TEMP_QR_CARD
import com.example.selfservicestation.databinding.ActivityMainBinding
import com.example.selfservicestation.enums.LockStateEnum
import com.example.selfservicestation.event.AudioEvent
import com.example.selfservicestation.event.CardEvent
import com.example.selfservicestation.event.ConfigChangeEvent
import com.example.selfservicestation.event.LoggedEvent
import com.example.selfservicestation.extensions.safeNavigate
import com.example.selfservicestation.global.GlobalParams
import com.example.selfservicestation.mob.MBFrame
import com.example.selfservicestation.mob.MODBUS_MIN_SEND_INTERVAL
import com.example.selfservicestation.mob.ModBusController
import com.example.selfservicestation.mob.ScanIdentityReceiver
import com.example.selfservicestation.mob.ScannerManager
import com.example.selfservicestation.singleton.SharedPreferenceUtil
import com.example.selfservicestation.util.Audio
import com.example.selfservicestation.util.Executor
import com.example.selfservicestation.util.LOG_TAG
import com.example.selfservicestation.util.Logger
import com.example.selfservicestation.util.Tip
import com.example.selfservicestation.util.getBitValueFrom8Bits
import com.example.selfservicestation.util.showToast
import com.example.selfservicestation.util.toHexString
import com.example.x6.gpioctl.GpioUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.LinkedList


class MainActivity : BaseBindingActivity<ActivityMainBinding>() {
    private var dm: DisplayMetrics? = null //屏幕分辨率容器
    private val logs = LinkedList<String>()
    private var maxLogLine = 30
    private val logsAdapter = TextlineAdapter()
    private lateinit var gpioUtils: GpioUtils

    // 中控模式下的扫码头管理器
    private val identityReceiver = ScanIdentityReceiver {
        Logger.i("HOME", "主页 扫码认证 *********************")
        onIdentityEvent(it)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        gpioUtils = GpioUtils.getInstance("/dev/rk_gpio")
        config485Data()
        val dm = resources.displayMetrics
        val width = dm.widthPixels
        val height = dm.heightPixels
        Log.i(LOG_TAG,"$width,,,$height")
        hideNavigationBar(this)
        initObservers()
    }

    fun hideNavigationBar(activity: Activity) {
        // 隐藏导航栏
        val decorView = activity.window.decorView
        val uiOptions = (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN)
        decorView.systemUiVisibility = uiOptions

        // 设置全屏参数
        activity.actionBar?.hide()
        activity.window.setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN
        )
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    fun onAudioEvent(eve: AudioEvent) {
        if (eve.resId != null) {
            Audio.play(applicationContext, eve.resId, eve.callback)
        }
        if (eve.file != null) {
            Audio.play(eve.file, eve.callback)
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onConfigChange(conf: ConfigChangeEvent){
        Log.i("ConfigChange","配置更改")
        config485Data()
    }


    private fun config485Data(){
        val doorOpenTime = SharedPreferenceUtil.getString(SP_DOOR_OPEN_TIME, DEFAULT_DOOR_OPEN_TIME)
        ScannerManager.stop()
        ScannerManager.start(this)
        ModBusController.start(this)
        ScannerManager.stopListenScanData(this)
        ScannerManager.startListenScanData(this){ scanData ->
            Log.d(LOG_TAG,"刷卡卡号：${scanData.data}----${scanData.index}")
            lifecycleScope.launch(Dispatchers.Main) {
                val doorPort = SharedPreferenceUtil.getInt(SP_CARD_DOOR_PORT, DEFAULT_CARD_DOOR_PORT)
                val lockPort = SharedPreferenceUtil.getInt(SP_CARD_PORT, DEFAULT_CARD_PORT)
                when(scanData.index){
                    //0 是开门用的，1是开锁用的
                    doorPort -> {
                        if (scanData.data == SharedPreferenceUtil.getString(SP_LOGIN_CARD, DEFAULT_LOGIN_CARD) || scanData.data == TEMP_QR_CARD){
                            gpioUtils.setGpioDirection(123, GpioUtils.GPIO_DIRECTION_OUT)
                            gpioUtils.gpioSetValue(123,GpioUtils.GPIO_VALUE_HIGH)
                            Tip.audio(R.raw.door_open)
                            delay(doorOpenTime.toLong() * 1000L)
                            gpioUtils.gpioSetValue(123,GpioUtils.GPIO_VALUE_LOW)
                        } else {
                            Tip.audio(R.raw.card_wrong)
                        }

                    }
                    lockPort -> {
                        if (scanData.data == SharedPreferenceUtil.getString(SP_LOCK_CARD, DEFAULT_LOCK_CARD) || scanData.data == TEMP_QR_CARD){
                            if (!GlobalParams.isFlowFinish){
                                Tip.audio(R.raw.please_wait_unit_flow_finish)
                                return@launch
                            }
                            GlobalParams.loginPhoneOrCard = scanData.data
                            checkLockState()
                        } else {
                            Tip.audio(R.raw.card_wrong)
                        }
                    }
                }
            }
        }
    }


    private fun checkLockState(){
        ModBusController.modBusManager?.sendTo(0, MBFrame(lockIndex = -1), false, MODBUS_MIN_SEND_INTERVAL) { resData ->
            Log.d("MainActivity", resData.toHexString(true))
            lifecycleScope.launch(Dispatchers.Main) {
                getLockDetailInfo(resData)
            }
        }
    }

    private fun getLockDetailInfo(byteArray: ByteArray){
        val lockCount = SharedPreferenceUtil.getInt(SP_LOCK_COUNT, DEFAULT_LOCK_COUNT)
        if (byteArray.size < 10) return
        val dataByteArray = byteArray.copyOfRange(5, byteArray.size - 1)
        Log.i("PhoneFragment",dataByteArray.toHexString())
        val bitList = arrayListOf<LockStateEnum>()
        outer@ for (item in dataByteArray){
            for (bitItem in 0..7){
                if(getBitValueFrom8Bits(item,bitItem) == 0){
                    bitList.add(LockStateEnum.OPEN)
                } else {
                    bitList.add(LockStateEnum.LOCK)
                }
                if (bitList.size == lockCount - 4) { //最多20个锁
                    break@outer
                }
            }
        }
        Log.i("PhoneFragment",bitList.toString())
        for ((index, item) in bitList.withIndex()){
            if (item == LockStateEnum.LOCK){
                openLock(index + 1)
                return
            }
        }
        showToast("所有的锁都已打开")
        Tip.audio(R.raw.all_phone_was_turn_on)
    }

    /**
     * 开锁，index从1开始
     */
    private fun openLock(index: Int){
        ModBusController.modBusManager?.sendTo(0, MBFrame(index - 1), false, MODBUS_MIN_SEND_INTERVAL) { resData ->
            Log.d("MainActivity", resData.toHexString(true))
            lifecycleScope.launch(Dispatchers.Main) {
                showToast("${index}号锁已打开")
                val bundle = bundleOf(EXTRA_LOCK_ON_NUM to index)
                findNavController(R.id.nav_host_fragment).safeNavigate(R.id.global_pocketSuccess,bundle)
            }
        }
    }

    override fun onResume() {
        super.onResume()
        Tip.audio(R.raw.welcome)

        gpioUtils.setGpioDirection(123, GpioUtils.GPIO_DIRECTION_OUT)
        gpioUtils.gpioSetValue(123,GpioUtils.GPIO_VALUE_LOW)
    }


    /**
     * 身份已识别事件
     */
    fun onIdentityEvent(eve: String) {
        Logger.d("IdEvent", "eve = $eve")
    }


    override fun getViewBinding(): ActivityMainBinding {
        return ActivityMainBinding.inflate(layoutInflater)
    }

    private fun initObservers() {
        lifecycleScope.launch {
            launch {
                GlobalParams.notifyResultFlow.collect {
                    binding.layoutBack.visibility = if (it) View.VISIBLE else View.GONE
                    binding.layoutSetting.visibility = if (it) View.GONE else View.VISIBLE
                }
            }
        }

        binding.layoutBack.setOnClickListener {
            findNavController(R.id.nav_host_fragment).navigateUp()
        }

        binding.layoutSetting.setOnClickListener {
           findNavController(R.id.nav_host_fragment).safeNavigate(R.id.homeFragment_to_configMenuFragment)
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onLoggedEvent(eve: LoggedEvent) {
            logs.add(eve.shortLog)
            if (logs.size > maxLogLine) {
                logs.removeFirst()
            }
            logsAdapter.submitList(logs)
            logsAdapter.notifyDataSetChanged()
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun cardEvent(eve: CardEvent){
        Log.d(LOG_TAG,"刷卡卡号e：${eve.cardNo}")
    }

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
    }

    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this)
    }
}